package com.starbaba.core.web.struts2;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import com.base.common.log.LogService;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;
import com.starbaba.controllog.aop.IActionLogAble;
import com.starbaba.controllog.model.ControlLogCategory;
import com.starbaba.core.hibernate.Page;
import com.starbaba.core.service.CommonService;
import com.starbaba.core.utils.ConvertUtils;
import com.starbaba.core.utils.IPUtil;
import com.starbaba.core.utils.PkUtils;
import com.starbaba.core.utils.PropertyParamMapBuilder;
import com.starbaba.core.utils.ReflectionUtils;
import com.starbaba.core.utils.Struts2Utils;
import com.starbaba.core.utils.json.JsonUtils;
import com.starbaba.core.web.constant.WebConstants;
import com.starbaba.core.web.control.annotation.Result;
import com.starbaba.core.web.control.annotation.Results;
import com.starbaba.core.web.page.PageRequest;
import com.starbaba.core.web.page.PageResponse;
import com.starbaba.system.logaccess.model.LogAccessVO;
import com.starbaba.system.managelog.model.OperAction;
import com.starbaba.system.managelog.model.OperState;
import com.starbaba.system.user.model.UserVO;

@SuppressWarnings({"serial","rawtypes","unchecked"})
public abstract class BaseAction extends ActionSupport implements
		IActionLogAble {

	protected Log log = LogFactory.getLog(this.getClass());

	private String ISEDIT = "FALSE";
	private String ISNEW = "FALSE";

	private CommonService service;

	protected Page page;

	protected Object entityVO;

	protected Object entityListVO;

	protected String[] pkNameArray;

	protected Class<?> voClass;

	protected Class<?> logClass;

	protected Object logVO;

	private boolean saveLog = false;

	protected UserVO userVO;

	protected PageRequest pageRequest;

	static SimpleDateFormat simpleDatedateFormat = new SimpleDateFormat(
			"yyyy-MM-dd HH:mm:ss");

	public Map<String, Object> paramsMap = new HashMap<String, Object>();

	public BaseAction() {
		/**
		 * 需要初始化voClass和pkNameArray
		 */
		userVO = (UserVO) Struts2Utils
				.getSessionAttribute(WebConstants.SESSION_ATTRIBUTE_USER);
	}

	protected CommonService getService() {
		return service;
	}

	@Autowired
	@Qualifier("commonServiceImpl")
	protected void setService(CommonService service) {
		this.service = service;
	}

	/**
	 * 无展现内容方法
	 * 
	 * @return
	 */
	public String show() {
		try {
			this.paramsMap.put("pageNo", WebConstants.DEFAULT_PAGENO);
			this.paramsMap.put("pageSize", WebConstants.DEFAULT_PAGESIZE);
			beforeShow();
		} catch (Exception ex) {
			this.addErrorMessage(ex.getMessage());
			log.error(ex, ex);
			return Action.ERROR;
		}
		return Action.SUCCESS;
	}

	/**
	 * 查询列表信息
	 * 
	 * @return
	 */
	public String list() {
		try {
			paramsMap = PropertyParamMapBuilder.buildFromHttpRequest(
					Struts2Utils.getRequest(), paramsMap);
			this.setParamsMapToTargetObject(paramsMap, this.getEntityListVO());
			beforeList();
			page = this.getService().doQuery(voClass, this.getEntityListVO());
		} catch (Exception ex) {
			log.error(ex, ex);
			this.addErrorMessage(ex.getMessage());
			return Action.ERROR;
		}
		return Action.SUCCESS;
	}

	/**
	 * 新增操作
	 * 
	 * @return
	 */
	public String add() {
		try {
			paramsMap = PropertyParamMapBuilder.buildFromHttpRequest(
					Struts2Utils.getRequest(), paramsMap);
			beforeAdd();
			this.setTargetObjectToParamsMap(entityVO, paramsMap);
			this.setIsEditAble(true);
			this.setIsNew(true);
		} catch (Exception ex) {
			log.error(ex, ex);
			this.addErrorMessage(ex.getMessage());
			return Action.ERROR;
		}
		return Action.SUCCESS;
	}

	/**
	 * 保存操作
	 * 
	 * @return
	 */
	public String save() {
		try {
			Date accesstime = new Date();
			String ip = IPUtil.getClientIP(Struts2Utils.getRequest());

			paramsMap = PropertyParamMapBuilder.buildFromHttpRequest(
					Struts2Utils.getRequest(), paramsMap);
			String isNew = (String) paramsMap
					.get(WebConstants.PAGE_ATTRIBUTE_ISNEW);
			this.setParamsMapToTargetObject(paramsMap, this.getEntityVO());
			if (WebConstants.STRING_TRUE.equals(isNew)) {
				beforeSave();
				if (this.isSaveLog()) {

					if (null == logClass) {
						logClass = LogAccessVO.class;
						// 记录新增操作日志
						String oprType = (voClass == null) ? "unknown"
								: voClass.getSimpleName().toLowerCase()
										.replaceFirst("vo$", "");
						logVO = this.getService().createAccesslogVO(
								userVO.getUserid(), accesstime, oprType,
								OperAction.INSERT, ip, this.getEntityVO(),
								null, OperState.SUCCESS);
					}

					entityVO = this.getService().doCreate(voClass,
							this.getEntityVO(), logClass, logVO);
				} else {
					entityVO = this.getService().doCreate(voClass,
							this.getEntityVO());
				}
				this.addMessage("保存成功");
				afterSave();
			} else {
				beforeUpdate();

				if (this.isSaveLog()) {

					if (null == logClass) {
						logClass = LogAccessVO.class;

						Object voOld = this.getService()
								.doFindByPk(
										voClass,
										PkUtils.getPkVO(voClass, pkNameArray,
												paramsMap));

						// 记录更新操作日志
						String oprType = (voClass == null) ? "unknown"
								: voClass.getSimpleName().toLowerCase()
										.replaceFirst("vo$", "");
						logVO = this.getService().createAccesslogVO(
								userVO.getUserid(), accesstime, oprType,
								OperAction.UPDATE, ip, voOld,
								this.getEntityVO(), OperState.SUCCESS);
					}

					entityVO = this.getService().doUpdate(voClass,
							this.getEntityVO(), logClass, logVO);
				} else {
					entityVO = this.getService().doUpdate(voClass,
							this.getEntityVO());
				}
				this.addMessage("修改成功");
				afterUpdate();
			}
			this.setTargetObjectToParamsMap(entityVO, paramsMap);
			this.setIsEditAble(false);
			this.setIsNew(false);
		} catch (Exception ex) {
			log.error(ex, ex);
			this.addErrorMessage("操作失败,失败原因:" + ex.getMessage());
			return Action.ERROR;
		}
		return Action.SUCCESS;
	}

	/**
	 * 修改
	 * 
	 * @return
	 */
	public String edit() {
		try {
			paramsMap = PropertyParamMapBuilder.buildFromHttpRequest(
					Struts2Utils.getRequest(), paramsMap);
			String pkValue = "";
			if (paramsMap.containsKey(WebConstants.REQUEST_ID)) {
				pkValue = (String) paramsMap.get(WebConstants.REQUEST_ID);
			}
			if (StringUtils.isNotBlank(pkValue)) {
				entityVO = this.getService().doFindByPk(voClass,
						PkUtils.getPkVO(voClass, pkNameArray, pkValue));
			}
			beforeEdit();
			this.setTargetObjectToParamsMap(entityVO, paramsMap);
			this.setIsEditAble(true);
			this.setIsNew(false);
		} catch (Exception ex) {
			log.error(ex, ex);
			this.addErrorMessage(ex.getMessage());
			return Action.ERROR;
		}
		return Action.SUCCESS;
	}

	/**
	 * 浏览操作
	 * 
	 * @return
	 */
	public String view() {
		try {
			paramsMap = PropertyParamMapBuilder.buildFromHttpRequest(
					Struts2Utils.getRequest(), paramsMap);
			String pkValue = "";
			if (paramsMap.containsKey(WebConstants.REQUEST_ID)) {
				pkValue = (String) paramsMap.get(WebConstants.REQUEST_ID);
			}
			if (StringUtils.isNotBlank(pkValue)) {
				entityVO = this.getService().doFindByPk(voClass,
						PkUtils.getPkVO(voClass, pkNameArray, pkValue));
			}
			beforeView();
			this.setTargetObjectToParamsMap(entityVO, paramsMap);
			this.setIsEditAble(false);// 最主要区别
			this.setIsNew(false);
		} catch (Exception ex) {
			log.error(ex, ex);
			this.addErrorMessage(ex.getMessage());
			return Action.ERROR;
		}
		return Action.SUCCESS;
	}

	/**
	 * 物理删除操作
	 * 
	 * @return
	 */
	public String delete() {

		try {
			Date accesstime = new Date();
			String ip = IPUtil.getClientIP(Struts2Utils.getRequest());

			paramsMap = PropertyParamMapBuilder.buildFromHttpRequest(
					Struts2Utils.getRequest(), paramsMap);
			String[] pkValues = this.getParamValueByParamsMap(paramsMap,
					WebConstants.REQUEST_ID);
			beforeDelete();
			if (null != pkValues && pkValues.length > 0)
				for (int index = 0; index < pkValues.length; index++) {

					if (this.isSaveLog()) {

						if (null == logClass) {
							logClass = LogAccessVO.class;
						}
						if (logClass == LogAccessVO.class) {
							// 记录删除操作日志

							String oprType = (voClass == null) ? "unknown"
									: ClassUtils.getShortClassName(voClass)
											.toLowerCase();
							entityVO = this.getService().doFindByPk(
									voClass,
									PkUtils.getPkVO(voClass, pkNameArray,
											pkValues[index]));
							logVO = this.getService().createAccesslogVO(
									userVO.getUserid(), accesstime, oprType,
									OperAction.DELETE, ip, entityVO, null,
									OperState.SUCCESS);
						}

						this.getService().doRemoveByPK(
								voClass,
								PkUtils.getPkVO(voClass, pkNameArray,
										pkValues[index]), logClass, logVO);

					} else {
						this.getService().doRemoveByPK(
								voClass,
								PkUtils.getPkVO(voClass, pkNameArray,
										pkValues[index]));
					}
				}
			afterDelete();
		} catch (Exception ex) {
			log.error(ex, ex);
			this.addErrorMessage(ex.getMessage());
			return Action.ERROR;
		}
		return Action.SUCCESS;
	}

	/**
	 * 逻辑删除，默认是把字段“状态state”设置为“无效—0”，字段“updateOprCode”设置为当前登录用户，字段“updateTime”
	 * 设置为当前系统时间
	 * 
	 * @return
	 *
	 * @Copyright: Copyright (c) 2006
	 * @Company: Revenco Tech Ltd.
	 * @anthor chenminhui<chenminhui@revenco.com>
	 * @since 2011-12-7 上午10:23:21
	 * @version V1.0
	 *
	 */
	@Results(value = { @Result(name = "success", location = "list.action"),
			@Result(name = "error", location = "list.action") })
	public String deleteLogic() {
		try {
			Date accesstime = new Date();
			String ip = IPUtil.getClientIP(Struts2Utils.getRequest());

			paramsMap = PropertyParamMapBuilder.buildFromHttpRequest(
					Struts2Utils.getRequest(), paramsMap);
			String[] pkValues = this.getParamValueByParamsMap(paramsMap, "PK");
			if (null != pkValues && pkValues.length > 0)
				for (int index = 0; index < pkValues.length; index++) {

					Object orgVO = this.getService().doFindByPk(
							voClass,
							PkUtils.getPkVO(voClass, pkNameArray,
									pkValues[index]));
					Object oldVO = BeanUtils.cloneBean(orgVO);

					beforeDeleteLogic(orgVO);

					if (this.isSaveLog()) {

						if (null == logClass) {
							logClass = LogAccessVO.class;
						}
						if (logClass == LogAccessVO.class) {
							logClass = LogAccessVO.class;

							// 记录逻辑删除操作日志
							String oprType = (voClass == null) ? "unknown"
									: voClass.getSimpleName().toLowerCase()
											.replaceFirst("vo$", "");
							logVO = this.getService().createAccesslogVO(
									userVO.getUserid(), accesstime, oprType,
									OperAction.UPDATE, ip, oldVO, orgVO,
									OperState.SUCCESS);
						}

						this.getService().doUpdate(voClass, orgVO, logClass,
								logVO);
					} else {
						this.getService().doUpdate(voClass, orgVO);
					}
				}
		} catch (Exception ex) {
			log.error(ex, ex);
			this.addErrorMessage(ex.getMessage());
			return Action.ERROR;
		}
		return Action.SUCCESS;
	}

	/**
	 * 进行逻辑删除时事件，默认是把字段“状态state”设置为“无效—0”，字段“updateOprCode”设置为当前登录用户，字段“
	 * updateTime”设置为当前系统时间
	 *
	 * @Copyright: Copyright (c) 2006
	 * @Company: Revenco Tech Ltd.
	 * @anthor chenminhui<chenminhui@revenco.com>
	 * @since 2011-12-7 上午10:28:28
	 * @version V1.0
	 *
	 */
	public void beforeDeleteLogic(Object vo) {
		if (vo == null)
			return;

		try {
			if (PropertyUtils.isWriteable(vo, "state")) {
				BeanUtils.setProperty(vo, "state", WebConstants.STATUS_INVALID);
			}
			if (PropertyUtils.isWriteable(vo, "updateTime")) {
				BeanUtils.setProperty(vo, "updateTime", new Date());
			}
			if (PropertyUtils.isWriteable(vo, "updateOprCode")) {
				BeanUtils.setProperty(vo, "updateOprCode", userVO.getUserid());
			}
		} catch (Exception e) {
			log.error(e, e);
		}

	}

	public String select() {
		return this.list();
	}

	public String txt() {
		return Action.SUCCESS;
	}

	public String excel() {
		try {
			paramsMap = PropertyParamMapBuilder.buildFromHttpRequest(
					Struts2Utils.getRequest(), paramsMap);
			this.setParamsMapToTargetObject(paramsMap, this.getEntityListVO());
			((BaseListVO) this.getEntityListVO())
					.setPageSize(WebConstants.DEFAULT_PAGESIZE_MAX_EXCEL);
			page = this.getService().doQuery(voClass, this.getEntityListVO());
		} catch (Exception ex) {
			log.error(ex, ex);
			this.addErrorMessage(ex.getMessage());
			return Action.ERROR;
		}
		return Action.SUCCESS;
	}

	/**
	 * 在新增操作之前业务处理
	 */
	protected void beforeAdd() throws Exception {

	}

	/**
	 * 新增保存之前业务处理
	 */
	protected void beforeSave() throws Exception {
	}

	/**
	 * 新增保存之后业务处理
	 */
	protected void afterSave() throws Exception {
	}

	/**
	 * 删除之后业务处理
	 */
	protected void afterDelete() throws Exception {
	}

	/**
	 * 修改之前业务处理
	 */
	protected void beforeUpdate() throws Exception {
	}

	/**
	 * 修改之后业务处理
	 */
	protected void afterUpdate() throws Exception {
	}

	/**
	 * 查询列表之前业务处理
	 */
	protected void beforeList() throws Exception {

	}

	/**
	 * 进入页面之前操作
	 */
	protected void beforeShow() throws Exception {

	}

	protected void beforeEdit() throws Exception {

	}

	/**
	 * 进入查看页面之前操作
	 */
	protected void beforeView() throws Exception {

	}

	/**
	 * 删除之前操作
	 */
	protected void beforeDelete() throws Exception {

	}

	/**
	 * 猜测方式猎取ListVO对象
	 * 
	 * @return
	 */
	public Object getEntityListVO() {
		if (null != entityListVO) {
			return entityListVO;
		}
		LogService.info("访问BaseAction getEntityListVO");
		String className = voClass.getName();
		// log.info("className======"+className);
		String listVOPreFix = StringUtils.substringBeforeLast(className, "VO")
				.replaceAll("\\.model\\.", ".view.");
		// log.info("listVOPreFix======"+listVOPreFix);
		String listVOClassName = listVOPreFix + "ListVO";
		try {
			entityListVO = Class.forName(listVOClassName).newInstance();
		} catch (Exception ex) {
		}

		if (null == entityListVO) {
			listVOClassName = StringUtils.substringBeforeLast(className, "VO")
					+ "ListVO";
			try {
				entityListVO = Class.forName(listVOClassName).newInstance();
			} catch (Exception ex) {
			}
		}
		// log.info("entityListVO.name======="+entityListVO.getClass().getName());
		return entityListVO;
	}

	public Object getEntityVO() throws Exception {
		try {
			if (null == entityVO) {
				entityVO = voClass.newInstance();
			}
		} catch (Exception ex) {
			throw new Exception(" voClass not fefinition or invalidate !");
		}
		return entityVO;
	}

	public void setEntityListVO(Object entityListVO) {
		this.entityListVO = entityListVO;
	}

	/**
	 * 根据目标对象设置ParamsMap值 说明：在设置过程中将目标对象值全部转为String类型保存至ParamsMap中 复杂类型转换说明：
	 * Date类型 yyyy-MM-dd HH:mm:ss 该方法不适用于对象中还有复杂实体对象
	 * 
	 * @param targetObject
	 * @param paramsMap
	 * @param Exception
	 * @return void
	 */
	protected void setTargetObjectToParamsMap(Object targetObject,
			Map<String, Object> paramsMap) throws Exception {
		if (null == targetObject)
			return;
		Field[] fields = ReflectionUtils.getDeclaredField(targetObject);
		Map propTypes = propertyTypes(targetObject.getClass());
		for (Field field : fields) {
			String fieldName = field.getName();
			if (!propTypes.containsKey(fieldName))
				continue;
			Class<?> type = field.getType();
			String fieldValue = "";
			if ("serialVersionUID".equalsIgnoreCase(fieldName.trim()))
				continue;
			if (type.getName().toLowerCase().indexOf("date") > 0) {
				Object date = ReflectionUtils.getFieldValue(targetObject,
						fieldName);
				if (null != date) {
					fieldValue = simpleDatedateFormat.format(date);
				}
			} else if (type.getName().toLowerCase().indexOf("time") > 0) {
				Object date = ReflectionUtils.getFieldValue(targetObject,
						fieldName);
				if (null != date) {
					fieldValue = simpleDatedateFormat.format(date);
				}
			} else {
				fieldValue = BeanUtils.getProperty(targetObject, fieldName);
			}
			if (StringUtils.isNotBlank(fieldValue)) {
				paramsMap.put(fieldName, fieldValue);
			}
		}
	}

	private static Map<String, Class<?>> propertyTypes(Class<?> voClass) {
		Map<String, Class<?>> map = new HashMap<String, Class<?>>();
		Method[] methods = voClass.getMethods();
		for (int i = 0; i < methods.length; i++) {
			String methodName = methods[i].getName();
			String property = null;
			if (methodName.startsWith("get")) {
				property = methodName.substring(3, 4).toLowerCase()
						+ methodName.substring(4);
			} else if (methodName.startsWith("is")) {
				property = methodName.substring(2, 3).toLowerCase()
						+ methodName.substring(3);
			} else {
				continue;
			}
			Class<?> type = methods[i].getReturnType();
			if (type != null)
				map.put(property, type);
		}
		return map;
	}

	/**
	 * 根据ParamsMap设置对象值
	 * 
	 * @param paramsMap
	 *            数据源
	 * @param targetObject
	 *            目标对象
	 * @param Exception
	 * @return void
	 * @throws
	 */
	protected void setParamsMapToTargetObject(Map<String, Object> paramsMap,
			Object targetObject) throws Exception {
		Map props = BeanUtils.describe(targetObject);
		for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
			String propertyName = (String) iter.next();
			if (paramsMap.containsKey(propertyName)) {
				String[] propertyValues = this.getParamValueByParamsMap(
						paramsMap, propertyName);
				Field field = ReflectionUtils.getDeclaredField(targetObject,
						propertyName);
				Class<?> type = field.getType();
				if (type.isArray()) {
					/**
					 * 数组类型, 先获取数组类型的具体类型
					 */
					Class<?> elementType = type.getComponentType();
					/**
					 * 在对应数组的情况下 如果页面单选时,此时传值非数组,而是字符串 如果页面为多选时,此时传值才为数组
					 */
					Object[] objValues = new Object[propertyValues.length];
					for (int i = 0; i < propertyValues.length; i++) {
						objValues[i] = ConvertUtils.convertStringToObject(
								propertyValues[i], elementType);
					}
					BeanUtils
							.setProperty(targetObject, propertyName, objValues);
				} else {
					/**
					 * 非数组类型,直接取第一个值
					 */
					BeanUtils.setProperty(targetObject, propertyName,
							ConvertUtils.convertStringToObject(
									propertyValues[0], type));
				}
			}
		}
	}

	/**
	 * 只负责取值,不负责判断paramsMap是否存在propertyName 另外说明：该方法返回为数组类型
	 * 
	 * @param @param paramsMap
	 * @param @param propertyName
	 * @param @return
	 * @param @throws Exception
	 * @return String[]
	 * @throws
	 */
	protected String[] getParamValueByParamsMap(Map<String, Object> paramsMap,
			String propertyName) throws Exception {
		Object values = paramsMap.get(propertyName);
		if (values instanceof java.lang.String[]) {
			return (String[]) values;
		} else {
			return new String[] { (String) values };
		}
	}

	public String getISEDIT() {
		return ISEDIT;
	}

	public void getISEDIT(String ISEDIT) {
		this.ISEDIT = ISEDIT;
	}

	public String getISNEW() {
		return ISNEW;
	}

	public void setISNEW(String ISNEW) {
		this.ISNEW = ISNEW;
	}

	public void setIsEditAble(boolean isEditAble) {
		if (isEditAble) {
			ISEDIT = WebConstants.STRING_TRUE;
		} else {
			ISEDIT = WebConstants.STRING_FALSE;
		}
	}

	public void setIsNew(boolean isnew) {
		if (isnew) {
			ISNEW = WebConstants.STRING_TRUE;
		} else {
			ISNEW = WebConstants.STRING_FALSE;
		}
	}

	public Map<String, Object> getParamsMap() {
		return paramsMap;
	}

	public void setParamsMap(Map<String, Object> paramsMap) {
		this.paramsMap = paramsMap;
	}

	public Page getPage() {
		return page;
	}

	public void setPage(Page page) {
		this.page = page;
	}

	/**
	 * Action 错误信息
	 * 
	 * @param @param errorMessage
	 * @return void
	 * @throws
	 */
	protected void addErrorMessage(String errorMessage) {
		if (StringUtils.isNotBlank(errorMessage)) {
			List<String> msgList = (List<String>) Struts2Utils.getRequest()
					.getAttribute(WebConstants.ERROR_MESSAGE);
			if (null != msgList && msgList.size() > 0) {
				msgList.add(errorMessage);
			} else {
				msgList = new ArrayList<String>();
				msgList.add(errorMessage);
				Struts2Utils.getRequest().setAttribute(
						WebConstants.ERROR_MESSAGE, msgList);
			}
		}
	}

	/**
	 * Action 操作信息
	 * 
	 * @param @param successMessage
	 * @return void
	 * @throws
	 */
	protected void addMessage(String successMessage) {
		if (StringUtils.isNotBlank(successMessage)) {
			List<String> msgList = (List<String>) Struts2Utils.getRequest()
					.getAttribute(WebConstants.DEFAULT_MESSAGE);
			if (null != msgList && msgList.size() > 0) {
				msgList.add(successMessage);
			} else {
				msgList = new ArrayList<String>();
				msgList.add(successMessage);
				Struts2Utils.getRequest().setAttribute(
						WebConstants.DEFAULT_MESSAGE, msgList);
			}
		}
	}

	/**
	 * @return userVO
	 */

	@Override
	public UserVO getUserVO() {
		return userVO;
	}

	/**
	 * @param userVO
	 *            the userVO to set
	 */
	public void setUserVO(UserVO userVO) {
		this.userVO = userVO;
	}

	public void setEntityVO(Object entityVO) {
		this.entityVO = entityVO;
	}

	public Object getLogVO() {
		return logVO;
	}

	public void setLogVO(Object logVO) {
		this.logVO = logVO;
	}

	public boolean isSaveLog() {
		return saveLog;
	}

	public void setSaveLog(boolean saveLog) {
		this.saveLog = saveLog;
	}

	public void setPageRequest(PageRequest pageRequest) {
		this.pageRequest = pageRequest;
	}

	/**
	 * 向页面输出JSON格式数据
	 * 
	 * @param jsonMessage
	 * @throws IOException
	 */
	protected void sendJsonMessage(String jsonMessage) throws IOException {
		HttpServletResponse response = Struts2Utils.getResponse();
		response.setCharacterEncoding(WebConstants.CHARACTER_ENCODING_UTF_8);
		response.getWriter().write(jsonMessage);
	}

	/**
	 * 向页面输出JSON格式数据
	 * 
	 * @param jsonMessage
	 * @throws IOException
	 */
	protected void sendErrorMessage(Exception e) throws IOException {
		JsonResult result = new JsonResult();
		result.setStatus("0");
		final Writer writer = new StringWriter();
		final PrintWriter printWriter = new PrintWriter(writer);

		e.printStackTrace(printWriter);
		result.setMessage(writer.toString());
		sendJsonMessage(result);
	}

	/**
	 * 向页面输出JSON格式数据
	 * 
	 * @param jsonMessage
	 * @throws IOException
	 */
	protected void sendJsonMessage(JsonResult result) throws IOException {
		this.sendJsonMessage(result.getJsonString());
	}

	/**
	 * 根据页面传过来的参数，构造页面数据请求
	 */
	protected void parsePageRequest() {
		pageRequest = new PageRequest();
		try {
			paramsMap = PropertyParamMapBuilder.buildFromHttpRequest(
					Struts2Utils.getRequest(), paramsMap);
			// 页面传过来的控制参数
			String jsondata = (String) paramsMap.get("aoData");

			int sEcho = 1;
			int iDisplayStart = 1;
			int iDisplayLength = WebConstants.DEFAULT_PAGESIZE;
			String sColumns = "";
			String orderby = null;
			String order = BaseListVO.ASC;

			HashMap<String, Object> pageParamsMap = new HashMap<String, Object>();
			if (!StringUtils.isBlank(jsondata)) {
				JSONArray jsonarray = JSONArray.fromObject(jsondata);
				for (int i = 0; i < jsonarray.size(); i++) {
					JSONObject obj = (JSONObject) jsonarray.get(i);
					pageParamsMap.put(obj.get("name").toString(),
							obj.get("value"));
				}
				sEcho = (Integer) pageParamsMap.get("sEcho");
				// 从第几项开始
				iDisplayStart = (Integer) pageParamsMap.get("iDisplayStart");
				// 一页多少项
				iDisplayLength = (Integer) pageParamsMap.get("iDisplayLength");
				// 要查询的列名，用,分隔
				sColumns = (String) pageParamsMap.get("sColumns");
				// 第几列要进行排序，下标从0开始
				int iSortCol_0 = (Integer) pageParamsMap.get("iSortCol_0");
				// 排序的规则"desc""asc"等
				order = (String) pageParamsMap.get("sSortDir_0");
				// 通过下标，找到要排序的列的名称
				String[] colArray = sColumns.split(",");
				if (colArray.length > iSortCol_0) {
					orderby = colArray[iSortCol_0];
				}
			}
			// 构造页面数据请求
			pageRequest.setSEcho(sEcho);
			pageRequest.setIDisplayStart(iDisplayStart);
			pageRequest.setIDisplayLength(iDisplayLength);
			pageRequest.setOrder(order);
			pageRequest.setOrderby(orderby);
			pageRequest.setSColumns(sColumns);

		} catch (Exception ex) {
			ex.printStackTrace();
			this.addActionMessage(ex.getMessage());
		}
	}

	protected void returnData() throws IOException {
		PageResponse pageResponse = new PageResponse();
		pageResponse.setAaData(page.getDatas());
		pageResponse.setITotalDisplayRecords(page.getTotalCount());
		pageResponse.setITotalRecords(page.getTotalCount());
		pageResponse.setSEcho(pageRequest.getSEcho());

		sendJsonMessage(JsonUtils.toJson(pageResponse, null, true, null, false));
	}

	public void data() {
		try {
			paramsMap = PropertyParamMapBuilder.buildFromHttpRequest(
					Struts2Utils.getRequest(), paramsMap);

			// 根据页面传过来的控制数据，构造页面数据请求
			parsePageRequest();

			page = new Page();
			page.setPageNo(pageRequest.getIDisplayStart()
					/ pageRequest.getIDisplayLength() + 1);
			page.setPageSize(pageRequest.getIDisplayLength());

			// 单表EntityListVO
			BeanUtils.copyProperties(this.getEntityListVO(), page);
			this.setParamsMapToTargetObject(paramsMap, this.getEntityListVO());

			((BaseListVO) this.getEntityListVO()).setOrder(pageRequest
					.getOrder());
			((BaseListVO) this.getEntityListVO()).setOrderBy(pageRequest
					.getOrderby());

			// 查询前处理,包含权限控制等
			beforeData();

			// 数据查询
			queryData();

			// 查询后处理,数据解析、封装
			afterData();

			returnData();
		} catch (Exception ex) {
			ex.printStackTrace();
			this.addActionMessage(ex.getMessage());
		}
	}

	protected void queryData() throws Exception {
		page = this.getService().doQuery(voClass, this.getEntityListVO());
	}

	protected void beforeData() throws Exception {
	}

	protected void afterData() throws Exception {
	}

	@Override
	public String getActionId() {
		return "0";
	}

	@Override
	public ArrayList<ControlLogCategory> getProduct() {
		return null;
	}

}
